class ParseBuffer
  attr_reader :cursor   
  def initialize(bs)
      @buffer = bs;
      @cursor = 0;
      @mark = 0;
      @limit = bs.length
  end
  
  def mark
      @mark = @cursor;
  end
  
  def reset
      @cursor = @mark;
  end
  
  def remaining
      return @limit - @cursor;
  end
  
  def setLength(newLength)
      if newLength then
          raise(ArgumentError, "Can't set new length if it exceeds buffer", caller) if (@cursor + newLength) > buffer.length
          @limit = @cursor + newLength
      end
  end
  
  #
  #
  #
  def hasRemaining
      return (@limit - @cursor) > 0 ? true : false;
  end
  
  #
  #
  #
  def get(len = nil)
      if len then
          raise(RuntimeError,"Invalid length field",caller) if (len > @limit - @cursor)
          output = @buffer.slice(@cursor,len);
          @cursor += len;
          return output;         
      else
          raise(RuntimeError,"End of buffer",caller) if @cursor >= @limit
          output = @buffer[@cursor];
          @cursor += 1;
          return output;    
      end     
  end
  
  #
  #
  #
  def getUnsignedWord
      raise(RuntimeError,"End of buffer",caller) if (@cursor + 1 >= @limit)
      value  = (@buffer[@cursor] & 0xFF) << 8;
      @cursor += 1;
      value += @buffer[@cursor] & 0xFF;
      @cursor += 1;
      return value;    
  end
  
  #
  #
  #
  def getDGILength
      raise(RuntimeError,"End of buffer",caller) if @cursor >= @limit
      
      i = 1;      
      if @buffer[@cursor] == 0xFF
          i = 2;
          @cursor += 1;
      end
    
      raise(RuntimeError,"Invalid DGI length field",caller) if (@cursor + i) > @limit
      
      dgiLength = 0;
      while i > 0
        dgiLength = (dgiLength << 8) | (@buffer[@cursor] & 0xFF);
        @cursor += 1
        i -= 1;
      end
            
      return dgiLength;    
  end
  
  #
  #
  #
  def getDERLength
      raise(RuntimeError,"End of buffer",caller) if @cursor >= @limit
            
      i = 1;       
      if (@buffer[@cursor] & 0x80) == 0x80
          i = @buffer[@cursor] & 0x07;
          @cursor += 1;
          if (i == 0)
            return -1;#Variable length BER encoding
          end
      end
    
      raise(RuntimeError,"More than 4 bytes in length field",caller) if i > 4      
      raise(RuntimeError,"Invalid DER length field",caller) if (@cursor + i) > @limit
      
      derLength = 0;
      len = 0;
      while i > 0 
        derLength = (derLength << 8) | ( @buffer[@cursor] & 0xFF);
        @cursor += 1;
        i -= 1;
      end     
      return derLength;    
  end
  
  #
  #
  #
  def getTag
      raise(RuntimeError,"End of buffer",caller) if @cursor >= @limit
      value = @buffer[@cursor] & 0xFF;
      @cursor += 1;
      if ((value & 0x1F) == 0x1F)
        i = 4;
        begin 
            raise(RuntimeError,"End of buffer",caller) if @cursor >= @limit
            value <<= 8;
            value += (@buffer[@cursor] & 0xFF);
            @cursor += 1;
            i -= 1;
        end while (((value & 0x80) == 0x80) && (i > 0));
      end
      return value;    
  end
  
end 